/*
 * Created on 2004-01-06
 */
package org.opencube.oms.meta;

import java.util.ArrayList;
import java.util.Date;

import org.opencube.oms.OMSNode;
import org.opencube.oms.util.OMSUtil;
import org.opencube.util.Constants;
import org.opencube.util.Util;

/**
 * @author <a href="mailto:maciek@fingo.pl">FINGO - Maciej Mroczko</a>
 * TODO: comment
 */
public class Datatype extends OMSNode
{
	/**
	 * The data type constant: string = 'string'.
	 */
	public static final String DATA_TYPE_STRING = "string";
	
	/**
		 * The data type constant: uniuque = 'date'.
	 */
	
	

	/**
	 * The data type constant: date = 'date'.
	 */
	public static final String DATA_TYPE_DATE = "date";

	/**
	 * The data type constant: integer = 'integer'.
	 */
	public static final String DATA_TYPE_INTEGER = "integer";

	/**
	 * The data type constant: float = 'float'.
	 */
	public static final String DATA_TYPE_FLOAT = "float";

	/**
	 * The data type constant: money = 'money'.
	 */
	public static final String DATA_TYPE_MONEY = "money";

	/**
	 * The data type constant: boolean = 'boolean'.
	 */
	public static final String DATA_TYPE_BOOLEAN = "boolean";

	/**
	 * The data type constant: text = 'text'.
	 */
	public static final String DATA_TYPE_TEXT = "text";
	
	/**
	 * The data type constant: binary = 'binary' 
	 */
	public static final String DATA_TYPE_BINARY = "binary";

	/* All valid data types */
	private String[] VALID_DATA_TYPES =
	{
		DATA_TYPE_STRING,
		DATA_TYPE_DATE,
		DATA_TYPE_INTEGER,
		DATA_TYPE_FLOAT,
		DATA_TYPE_MONEY,
		DATA_TYPE_BOOLEAN,
		DATA_TYPE_BINARY,
		DATA_TYPE_TEXT
		
	};

	/**
	 * The type constant: simple = 's' 
	 */
	public static final char TYPE_SIMPLE = 's'; 
	/** 
	 * The type constant: blob = 'b' 
	 */
	public static final char TYPE_BLOB = 'b'; 
	/**
	 * The type constant: simple = 's' 
	 */
	public static final char TYPE_CLOB = 'c'; 
	
	/**
		 * The type constant: simple = 's' 
	*/
	public static final char TYPE_UNIQUE = 'u';

	/* The namespace */
	private boolean isUnique=false;
	private Namespace namespace = null;
	/* The values of this domain */
	private ArrayList datatypeEnumerations = new ArrayList();
	/* The attribute data type */
	private String typeName = DATA_TYPE_STRING;
	
	/**
	 * @param namespace
	 * @param id
	 * @param name
	 * @param creatingDate
	 * @param creater
	 * @param modifyingDate
	 * @param modifier
	 * 
	 * @throws OMSMetaDataException
	 */
	Datatype( Namespace namespace, String typeName, String id, String name,boolean isUnique, Date creatingDate, String creater, Date modifyingDate, String modifier )
	throws OMSMetaDataException
	{
		super( id, name, creatingDate, creater, modifyingDate, modifier );
		this.namespace = namespace;
		this.typeName = typeName;
		this.isUnique = isUnique;
		namespace.getMetaData().addDatatype( this );
		if( namespace == null )
		{
			throw new OMSMetaDataException( "The meta data for the datatype cannot be bull: name = '" + name + "', id = '" + id + "'" );
		}
		if( !Util.inArray( VALID_DATA_TYPES, typeName ) )
		{
			throw new OMSMetaDataException( "Invalid type name '" + typeName + "' for the datatype: name = '" + name + "', id = '" + id + "'" );
		}
	}
	
	/**
	 * @param use
	 * @param id
	 * @param name
	 * @param creatingDate
	 * @param creater
	 * @param modifyingDate
	 * @param modifier
	 * 
	 * @return Datatype
	 * 
	 * @throws OMSMetaDataException
	 */
	
	public DatatypeEnumeration createDatatypeEnumeration( char use, String id, String name, Date creatingDate, String creater, Date modifyingDate, String modifier )
	throws OMSMetaDataException
	{
		DatatypeEnumeration den = new DatatypeEnumeration( this, use, id, name, creatingDate, creater, modifyingDate, modifier );
		datatypeEnumerations.add( den ); 
		return den;
	}

	/**
	 * Returns the datatype enumeration with the given id
	 * 
	 * @param id - the id of datatype enumeration to find
	 * 
	 * @return DatatypeEnumeration - the datatype enumeration with the given id or null if not found
	 */
	public DatatypeEnumeration getDatatypeEnumerationById( String id ) throws OMSMetaDataException
	{
		DatatypeEnumeration den = (DatatypeEnumeration) OMSUtil.getNodeById( datatypeEnumerations, id );
		if( den == null )
		{
			throw new OMSMetaDataException( "Datatype enumeration with id '" + id + "' not found in the datatype '" + namespace.getPath() + Constants.STR_SLASH + this.name + "'" );
		}
		return den;
	} 
	
	/**
	 * Returns the datatype enumeration with the given name
	 * 
	 * @param name - the name of datatype enumeration to find
	 * 
	 * @return DatatypeEnumeration - the datatype enumeration with the given name or null if not found
	 */
	public DatatypeEnumeration getDatatypeEnumerationByName( String name ) throws OMSMetaDataException
	{
		DatatypeEnumeration den = (DatatypeEnumeration) OMSUtil.getNodeByName( datatypeEnumerations, name );
		if( den == null )
		{
			throw new OMSMetaDataException( "Datatype enumeration '" + name + "' not found in the datatype '" + namespace.getPath() + Constants.STR_SLASH + this.name + "'" );
		}
		return den;
	} 

	/**
	 * Returns all datatype enumerations of this datatype
	 * 
	 * @return DatatypeEnumeration[] - all datatype enumerations of this datatype
	 */
	public DatatypeEnumeration[] getDatatypeEnumerations()
	{
		return ( DatatypeEnumeration[] ) datatypeEnumerations.toArray( new DatatypeEnumeration[ datatypeEnumerations.size() ] );
	}
	
	/**
	 * Returns the namespace
	 * 
	 * @return Namespace
	 */
	public Namespace getNamespace()
	{
		return namespace;
	}
	
	/**
	 * Returns the type name
	 * 
	 * @return The type name
	 */
	public String getTypeName()
	{
		return typeName;
	}
	public boolean getIsUnique(){
		return isUnique;
	}
	public char getType()
	{
		if( getIsUnique() )
		{
			
			return TYPE_UNIQUE;
		}
		if( DATA_TYPE_BINARY.equals( typeName ) )
		{
			return TYPE_BLOB;
		}
		else if( DATA_TYPE_TEXT.equals( typeName ) )
		{
			return TYPE_CLOB;
		}
		else
		{
			return TYPE_SIMPLE;
		}
	}

	/*
	 * (non-Javadoc)
	 * @see java.lang.Object#toString()
	 */
	public String toString()
	{
		String result = "<datatype name=\"" + name + "\" id=\"" + id + "\">";
		if( datatypeEnumerations.size() > 0 )
		{
			for( int i = 0; i < datatypeEnumerations.size(); i++ )
			{
				result += Util.indent( datatypeEnumerations.get( i ).toString() );
			}
			result += "\n</domain>";
		}
		else
		{
			result += "/>";
		}
		
		return result;
	}
	
	public boolean isMultiple()
	{
		return datatypeEnumerations.size() > 1;
	}
	
	public boolean isSimple()
	{
		return getType() == TYPE_SIMPLE;
	}
	
	public boolean isClob()
	{
		return getType() == TYPE_CLOB;
	}
	public boolean isBlob()
	{
		return getType() == TYPE_BLOB;
	}
}
